map = new Object();
maps = new Object();

// Some variables
map.count = 0;
map.loaded = 0;
map.current;

map.camera = new Object();
map.camera.x = 0;
map.camera.y = 0;

map.tilewidth = 16; // Screen holds 30x17 @ 16px

map.camera.centerOnArr = function(pos) {
    return map.camera.centerOn(pos[0], pos[1]);
}
map.camera.centerOn = function(x, y) {
    map.camera.x = Math.round(x - (480 - map.tilewidth) / 2);
    map.camera.y = Math.round(y - (270 - map.tilewidth) / 2);
    map.camera.x = map.camera.x < 0 ? 0 : map.camera.x;
    map.camera.y = map.camera.y < 0 ? 0 : map.camera.y;
    map.camera.x = map.camera.x + 480 > map.tilewidth * map.current.width ? map.tilewidth * map.current.width - 480 : map.camera.x;
    map.camera.y = map.camera.y + 270 > map.tilewidth * map.current.height ? map.tilewidth * map.current.height - 270 : map.camera.y;
    //console.log("(" + x + "," + y + ")");
}

map.draw = function() {
    // Center the camera on the player
    map.camera.centerOnArr(game.playerEntity.getTruePos());
    
    var bg = map.current.background;
    var fg = map.current.foreground;
    // Clear canvases
    $bgCanvas.clearCanvas();
    $fgCanvas.clearCanvas();
    // Draw background
    for (var i = 0; i < bg.length; i++) {
        if (bg[i] != 0) {
            var p = map.XYFromi(i);
            var c = [p[0] * map.tilewidth, p[1] * map.tilewidth];
            if (c[0] + map.tilewidth >= map.camera.x
             && c[0] <= map.camera.x + 480
             && c[1] + map.tilewidth >= map.camera.y
             && c[1] <= map.camera.y + 270) {
                $bgCanvas.drawSprite({
                    sprite: sprites[map.terrain[bg[i]]],
                    x: c[0] - map.camera.x,
                    y: c[1] - map.camera.y
                });
            }
        }
    }
    // Draw foreground
    for (var i = 0; i < fg.length; i++) {
        if (fg[i] != 0) {
            var p = map.XYFromi(i);
            var c = [p[0] * map.tilewidth, p[1] * map.tilewidth];
            if (c[0] + map.tilewidth >= map.camera.x
             && c[0] <= map.camera.x + 480
             && c[1] + map.tilewidth >= map.camera.y
             && c[1] <= map.camera.y + 270) {
                $bgCanvas.drawSprite({
                    sprite: sprites[map.terrain[fg[i]]],
                    x: c[0] - map.camera.x,
                    y: c[1] - map.camera.y
                });
            }
        }
    }
}

map.set = function(_map) {
    map.current = maps[_map];
    // Clear entities
    entities.collisions = newFilledArray(map.current.width * map.current.height, 0);
    entities.list = [];
    // Recreate player
    game.playerEntity = new EntityPlayer('player_boy3');
    // Populate with entities
    $.each(map.current.entities, function(k, entity) {
        new EntityNPC(entity);
    });
}

map.load = function() {
    // Define the list of maps
    var mapList = [
        'maps/map_test.json',
        'maps/map_editor_test.json'
    ];
    map.count = mapList.length + 1;
    
    // Load maps
    $.each(mapList, function(index, value) {
        $.getJSON(value, function(data) {
            maps[data.id] = data;
            map.loaded++;
            console.log('Loaded "' + value + '"');
        }).fail(function(value) {
            return game.ajaxError(value);
        }(value));
    });
    
    // Load terrain ids
    $.getJSON('maps/terrain.json', function(data) {
        map.terrain = data;
        map.loaded++;
        console.log('Loaded "maps/terrain.json"');
    }).fail(function(value) {
        return game.ajaxError(value);
    }('maps/terrain.json'));
}

map.iFromXYArr = function(pos, _map) {
    return map.iFromXY(pos[0], pos[1], _map);
}

map.iFromXY = function(x, y, _map) {
    _map = (typeof _map == 'undefined' ? map.current : _map);
    return _map.width * y + x;
}

map.XYFromi = function(i, _map) {
    _map = (typeof _map == 'undefined' ? map.current : _map);
    return [i % _map.width, Math.floor(i / _map.width)];
}